﻿using GN.Pay.Client.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using GN.Pay.Client.Services;
using GN.Pay.Client.Manager;
using Newtonsoft.Json.Linq;

namespace GN.Pay.Client.Impl
{
    /// <summary>
    /// 服务客户端
    /// </summary>
    public class ServiceClient : IServiceClient
    {
        private static JsonSerializerSettings CamelCase_Setting = new JsonSerializerSettings()
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };

        private static JsonSerializerSettings Default_Setting = new JsonSerializerSettings()
        {
            ContractResolver = new DefaultContractResolver()
        };

        private readonly IPayConfigure payConfigure;
        private ServiceRequestManager serviceRequest;

        /// <summary>
        /// 实例化 RequestClient 类新实例
        /// </summary>       
        public ServiceClient()
            : this(PayConfigureUtils.ConfigFileToPayConfigure())
        {
        }

        /// <summary>
        /// 实例化 RequestClient 类新实例
        /// </summary>
        /// <param name="payConfigure">支付配置</param>
        public ServiceClient(IPayConfigure payConfigure)
        {
            this.payConfigure = ServiceUtils.CheckPayConfigure(payConfigure);
            this.GatewayPath = "gateway/go";
            this.Encoding = Encoding.UTF8;
            this.CamelCase = true;
            this.serviceRequest = new ServiceRequestManager(this);
        }

        private string CheckStringValue(string value, string argName)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                throw new ArgumentNullException(argName);
            }
            return argName;
        }


        /// <summary>
        /// 获取服务器置
        /// </summary>
        public IPayConfigure PayConfigure
        {
            get
            {
                return this.payConfigure;
            }
        }

        /// <summary>
        /// 获取网关路径
        /// </summary>
        public string GatewayPath { get; private set; }

        /// <summary>
        /// 获取编码
        /// </summary>
        public Encoding Encoding { get; set; }

        /// <summary>
        /// 获取是否骆锋命名
        /// </summary>
        public bool CamelCase { get; set; }

        private JsonSerializerSettings GetJsonSerializerSettings
        {
            get
            {
                if (this.CamelCase)
                {
                    return CamelCase_Setting;
                }
                return Default_Setting;
            }
        }

        #region 调用服务

        /// <summary>
        /// 调用服务
        /// </summary>
        /// <param name="serviceName"></param>
        public void CallService(string serviceName)
        {
            this.serviceRequest.ServiceRequest<string>(serviceName, null);
        }

        /// <summary>
        /// 调用服务
        /// </summary>
        /// <param name="serviceName"></param>
        public TResult CallService<TResult>(string serviceName)
        {
            return this.serviceRequest.ServiceRequest<string, TResult>(serviceName, null);
        }

        /// <summary>
        /// 调用服务
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <param name="serviceName"></param>
        /// <param name="request"></param>
        public void CallService<TRequest>(string serviceName, TRequest request)
            where TRequest : class
        {
            this.serviceRequest.ServiceRequest<TRequest>(serviceName, request);
        }

        /// <summary>
        /// 调用服务
        /// </summary>
        /// <typeparam name="TRequest">请求类型</typeparam>
        /// <typeparam name="TResult">响应类型</typeparam>
        /// <param name="serviceName">服务名称</param>
        /// <param name="request">请求</param>
        /// <returns></returns>
        public TResult CallService<TRequest, TResult>(string serviceName, TRequest request)
             where TRequest : class
        {
            return this.serviceRequest.ServiceRequest<TRequest, TResult>(serviceName, request);
        }

        #endregion

        private TService GetOrCreateService<TService>(ref TService service, Func<TService> fun)
        {
            if (service == null)
            {
                lock (this)
                {
                    if (service == null)
                    {
                        service = fun();
                    }
                }
            }
            return service;
        }

        private ITradeApplyService tradeApplyService;

        /// <summary>
        /// 获取申请服务
        /// </summary>
        public ITradeApplyService TradeApplyService
        {
            get
            {
                return this.GetOrCreateService(ref this.tradeApplyService,
                    () => { return new TradeApplyService(this); });
            }
        }

        private ITradeQueryService tradeQueryService;

        /// <summary>
        /// 获取交易查询服务
        /// </summary>
        public ITradeQueryService TradeQueryService
        {
            get
            {
                return this.GetOrCreateService(ref this.tradeQueryService,
                    () => { return new TradeQueryService(this); });
            }
        }

        private IMerchantMemberService merchantMemberService;

        /// <summary>
        /// 获取商户会员服务
        /// </summary>
        public IMerchantMemberService MerchantMemberService
        {
            get
            {
                return this.GetOrCreateService(ref this.merchantMemberService,
                   () => { return new MerchantMemberService(this); });
            }
        }

        private INotifyService notifyService;

        /// <summary>
        /// 获取通知服务
        /// </summary>
        public INotifyService NotifyService
        {
            get
            {
                return this.GetOrCreateService(ref this.notifyService,
                    () => { return new NotifyService(this); });
            }
        }

        /// <summary>
        /// 命令请求
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <param name="jsonParams">Json参数</param>
        /// <returns></returns>
        public JToken CommandRequest(string serviceName, string jsonParams)
        {
            return serviceRequest.CommandRequest(serviceName, jsonParams);
        }
    }
}
